/**
 * 
 */
package com.maywide.jdp.system.bean;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Query;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.maywide.jdp.core.exception.AppException;
import com.maywide.jdp.core.vo.Page;
import com.maywide.jdp.dao.Dao;
import com.maywide.jdp.dao.PageQueryTemplate;
import com.maywide.jdp.dao.QueryTemplate;
import com.maywide.jdp.system.entities.Operator;
import com.maywide.jdp.system.entities.Organization;
import com.maywide.jdp.system.vo.OrganizationTree;

/**
 * 机构管理Bean
 * 
 * @author luoyang
 * @version 1.0
 * @since JDK1.6
 */
@Component("organizationBean")
@Transactional(propagation = Propagation.REQUIRED)
public class OrganizationBeanImpl implements OrganizationBean {
	private static final String APP_TYPE_BASE = "base";
	private static final String APP_TYPE_OPERATORS = "operators";

	/**
	 * 基础DAO
	 */
	private Dao dao = null;

	/**
	 * @param dao
	 *            the dao to set
	 */
	@Autowired
	public void setDao(Dao dao) {
		this.dao = dao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.maywide.jdp.core.bean.BaseBean#insert(java.lang.Object)
	 */
	@Override
	public void insert(Object obj) throws Exception {
		dao.insert(obj);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.maywide.jdp.core.bean.BaseBean#update(java.lang.Object)
	 */
	@Override
	public void update(Object obj) throws Exception {
		Organization organizationVO = ((Organization) obj);

		String id = organizationVO.getId();
		Organization organization = dao.find(Organization.class, id);

		// 取得不可改变属性
		Organization parent = organization.getParent();
		List<Organization> subs = organization.getSubs();

		organizationVO.setParent(parent);
		organizationVO.setSubs(subs);
		BeanUtils.copyProperties(organizationVO,organization);

		dao.update(organization);
	}

	@Override
	public void updateApp(Organization organizationVO, String appType)
			throws Exception {
		String id = organizationVO.getId();

		if (appType.equals(APP_TYPE_BASE)) {
			// 取得不可改变属性
			Organization organization = dao.find(Organization.class, id);
			Organization parent = organization.getParent();
			List<Organization> subs = organization.getSubs();
			List<Operator> operators = organization.getOperators();

			organizationVO.setParent(parent);
			organizationVO.setSubs(subs);
			organizationVO.setOperators(operators);
			BeanUtils.copyProperties(organizationVO,organization);

			dao.update(organization);
		} else if (appType.equals(APP_TYPE_OPERATORS)) {
			List<Operator> operators = organizationVO.getOperators();
			Organization organization = (Organization) dao.find(
					Organization.class, id);
			organization.setOperators(operators);
			dao.update(organization);
		} else {
			throw new AppException("未知的应用类型!");
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public void remove(Class clazz, Serializable id) throws Exception {
		Object obj = dao.find(clazz, id);
		dao.remove(obj);
	}

	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public Object load(Serializable id) throws Exception {
		Organization organization = dao.find(Organization.class, id);
		return organization;
	}

	@Override
	public void lock(String id) throws Exception {
		String jql = "update Organization as o set o.active = false where o.id = :id";
		Query query = dao.createQuery(jql);
		query.setParameter("id", id);
		query.executeUpdate();
	}

	@Override
	public void lockAll(String[] ids) throws Exception {
		String hql = "update Organization as o set o.active = false where o.id in (:ids)";
		Map<String, Object> conditions = new HashMap<String, Object>();
		conditions.put("ids", ids);
		dao.executeUpdate(hql, conditions);
	}

	@Override
	public void unlock(String id) throws Exception {
		String jql = "update Organization as o set o.active = true where o.id = :id";
		Query query = dao.createQuery(jql);
		query.setParameter("id", id);
		query.executeUpdate();
	}

	@Override
	public void unlockAll(String[] ids) throws Exception {
		String hql = "update Organization as o set o.active = true where o.id in (:ids)";
		Map<String, Object> conditions = new HashMap<String, Object>();
		conditions.put("ids", ids);
		dao.executeUpdate(hql, conditions);
	}

	@Override
	public void move(String id, String parentID) throws Exception {
		String jql = "update Organization as o set o.parent.id = :parentID where o.id = :id";
		Query query = dao.createQuery(jql);
		int row = 0;
		query.setParameter("id", id);
		query.setParameter("parentID", parentID);
		row = query.executeUpdate();
		if (row <= 0)
			throw new AppException("未发生移动操作!");
	}

	@Override
	public void move(List<String> ids, String parentID) throws Exception {
		int row = 0;
		String hql = "update Organization as o set o.parent.id = :parentID where o.id in (:ids)";
		Map<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("ids", ids);
		parameters.put("parentID", parentID);
		row = dao.executeUpdate(hql, parameters);
		if (row <= 0)
			throw new AppException("未发生移动操作!");
	}

	@SuppressWarnings({ "rawtypes" })
	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List tree(Map<String, Object> parameters) throws Exception {
		StringBuffer buf = new StringBuffer().append(
				"select distinct o.ID as id,").append("o.ORG_CODE as code,")
				.append("o.ORG_NAME as name,").append("o.ORG_NAME as text,")
				.append("o.ORG_TYPE as type,").append(
						"o.ORG_ADDRESS as address,").append(
						"o.ORG_PHONE as phone,").append(
						"o.ORG_MOBILE as mobile,").append("o.ORG_FAX as fax,")
				.append("o.ORG_EMAIL as email,").append(
						"o.ORG_PARENT_ID as parentID,").append(
						"o.ORG_PRINCIPAL as principal,").append(
						"o.ORG_DESC as description,").append(
						"o.ORG_ACTIVE as active,").append(
						"decode(sign(count(sub.ID)),1,0,1) as leaf").append(
						" from SYS_ORGANIZATION o").append(" left join")
				.append(" SYS_ORGANIZATION sub on o.ID = sub.ORG_PARENT_ID")
				.append(" where");
		if (parameters.containsKey("parentID"))
			buf
					.append(" o.ID IN(SELECT org.ID FROM SYS_ORGANIZATION org WHERE org.ORG_PARENT_ID = :parentID AND org.ORG_ACTIVE = 1)");
		else if (parameters.containsKey("rootID"))
			buf.append(" o.ID = :rootID");
		else
			buf
					.append(" o.ID IN(SELECT org.ID FROM SYS_ORGANIZATION org WHERE org.ORG_PARENT_ID IS NULL AND org.ORG_ACTIVE = 1)");
		buf.append(" and");
		buf.append(" o.ORG_ACTIVE = 1 and o.REMOVED = 0");
		buf
				.append(" group by o.ID,o.ORG_CODE,o.ORG_NAME,o.ORG_TYPE,o.ORG_ADDRESS,o.ORG_PHONE,o.ORG_MOBILE,o.ORG_FAX,o.ORG_EMAIL,o.ORG_PARENT_ID,o.ORG_PRINCIPAL,o.ORG_DESC,o.ORG_ACTIVE");

		String sql = buf.toString();
		return dao
				.executeNativeQuery(sql, parameters, OrganizationTree.class,
						"com.maywide.jdp.system.entities.Organization.organizationTree");
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<Organization> list(String sort, String dir,
			Map<String, Object> conditions, Map<String, Object> parameters)
			throws Exception {
		List<Organization> list = null;
		String queryString = "select distinct o from Organization as o";
		if (conditions == null || conditions.isEmpty()) {
			if (conditions == null)
				conditions = new HashMap<String, Object>();
			conditions.put("noParentID", null);
		}
		if (conditions.containsKey("operatorID"))
			queryString = "select distinct o from Organization as o inner join o.operators as op";

		QueryTemplate template = new QueryTemplate(queryString, sort, dir);
		list = dao.executeListQuery(template, conditions, parameters);
		if (list != null && !list.isEmpty()) {
			for (Organization organization : list) {
				organization.getPath();
			}
		}
		return list;
	}

	@Override
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public Page page(int first, int limit, String sort, String dir,
			Map<String, Object> conditions, Map<String, Object> parameters)
			throws Exception {
		Page page = null;
		String queryString = "select o from Organization as o";
		String countQueryString = "select count(o.id) from Organization as o";
		if (conditions == null)
			conditions = new HashMap<String, Object>();
		if (!conditions.containsKey("parentID")
				&& !conditions.containsKey("rootID"))
			conditions.put("noParentID", null);
		PageQueryTemplate template = new PageQueryTemplate(queryString,
				countQueryString, first, limit, sort, dir);
		page = dao.executePageQuery(template, conditions, parameters);

		return page;
	}

	@SuppressWarnings("unchecked")
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	@Override
	public List<Organization> findAllLeaf() throws Exception {
		Query query = dao
				.createNamedQuery("com.maywide.jdp.system.entities.Organization.findAllLeaf");
		return query.getResultList();
	}

}
